#include<muduo/net/TcpClient.h>
#include<muduo/net/EventLoopThread.h> 
#include<muduo/net/TcpConnection.h>
#include<muduo/base/CountDownLatch.h>
#include<iostream>

class TranslateClient
{
private:
    muduo::CountDownLatch _latch;//保证只有服务器端接受了客户端的连接，客户端才开始向服务器端发送数据
    //大于0才会进入wait的逻辑，所以此处初始化为1
    muduo::net::EventLoopThread _loopthread;//事件监控
    muduo::net::TcpClient _client;
    muduo::net::TcpConnectionPtr _conn;
private:
    //连接建立成功就唤醒 connect连接的阻塞线程
    void OnConnetcion(const muduo::net::TcpConnectionPtr& conn)
    {
        if(conn->connected()==true)//建立连接成功
        {
            _latch.countDown();//唤醒主线程当中的阻塞？
            _conn = conn;//连接创建成功
        }
        else
        {
            //连接关闭的操作
            _conn.reset();//?reset的功能是什么?调用swap与临时对象进行交换，就释放了对象相当于释放了连接
        }
    }

    void OnMessage(const muduo::net::TcpConnectionPtr& conn , muduo::net::Buffer* buf , muduo::Timestamp)
    {
        //客户端收到的数据就是翻译结构
        std::cout << "翻译结果: " << buf->retrieveAllAsString() << std::endl;
    }

public:
    TranslateClient(const std::string & sip , int sport)
    :_latch(1)
    ,_client(_loopthread.startLoop(), muduo::net::InetAddress(sip ,sport) , "TranslateClient")
    {
        //设置_client的回调函数
        _client.setConnectionCallback(std::bind(&TranslateClient::OnConnetcion, this , std::placeholders::_1));
        _client.setMessageCallback(std::bind(&TranslateClient::OnMessage, this , std::placeholders::_1,std::placeholders::_2, std::placeholders::_3));
    }
    //连接服务器，需要阻塞等待连接建立成功之后再返回
    void connect()
    {   
        _client.connect();//向服务器发起连接请求
        _latch.wait();//阻塞等待，直到连接与服务器建立成功
    }
    bool send(const std::string& msg)
    {
        //只有当连接建立成功才发送数据
        if(_conn->connected())
        {
            //发送数据
            _conn->send(msg);
            return true;
        }
        return false;
    }

    ~TranslateClient(){}
};

int main()
{
    TranslateClient client("127.0.0.1" , 8888);
    client.connect();//向服务器发起连接请求,连接成功才会向下走

    while(1)
    {
        std::string buf;
        std::cin >> buf;
        client.send(buf);
    }
    return 0;
}